#ifndef VISBASEELEMENT_H
#define VISBASEELEMENT_H

#include <QObject>
#include <QGraphicsWidget>
#include <QDebug>
#include <QPointer>
#include <QGraphicsSceneHoverEvent>

class VisBaseWidget;
class SageVis;
class VisBaseContainer;

//Connection types
#define     HEIGHT_CONNECTION     0
#define     WIDTH_CONNECTION     1
#define     XPOS_CONNECTION     2
#define     YPOS_CONNECTION     3
#define     GEOMETRY_CONNECTION     4
#define     HOVER_CONNECTION    5
#define     UPDATE_CONNECTION   6
#define     COLOR_CONNECTION    7

#define CENTER_LINE_CONNECTION    0
#define TOP_RIGHT_LINE_CONNECTION   1
#define TOP_LEFT_LINE_CONNECTION    2
#define BOTTOM_RIGHT_LINE_CONNECTION   3
#define BOTTOM_LEFT_LINE_CONNECTION     4
#define CENTER_LEFT_LINE_CONNECTION     5
#define CENTER_RIGHT_LINE_CONNECTION    6
#define BOTTOM_CENTER_LINE_CONNECTION   7
#define TOP_CENTER_LINE_CONNECTION    8
#define ABSOLUTE_COORDINATE_LINE_CONNECTION 9
#define RELATIVE_COORDINATE_LINE_CONNECTION 10

class VisBaseElement : public QGraphicsWidget
{
    Q_OBJECT
public:
    VisBaseElement(QPointer<SageVis> sageVisPointer, QPointer<VisBaseWidget> parentWidget, QGraphicsItem *parent = 0);

    friend class VisBasContainer;
    typedef QGraphicsWidget super;

    //SETUP appearance of the element
    virtual void setWidth( float w );
    virtual void setHeight( float h );
    //void setWidth( int w );
    //void setHeight( int h );

    //SHAPE AND SIZE FUNCTIONS
    virtual void setGeometry(const QRectF &geom);
    virtual void setGeometry( qreal x, qreal y, qreal w, qreal h );
    QRectF boundingRect() const;
    QPainterPath shape() const;

    //CONNECTION FUNCTIONS
    virtual void forgeConnection( QPointer< VisBaseElement > e, int type );
    static void forgeConnection( QPointer< VisBaseElement > e1, QPointer< VisBaseElement > e2, int type );

    //LINE CONNECTION FUNCTIONS
    QPointF getLineConnectionPoint() const;//the line connector element attaches here
    QPointF getLineConnectionPoint(int type) const;
    void setLineConnectionType( int type );

    void update();

    virtual QString getUniqueId();

    //handling signals and slots
    virtual void processHoverEvent(QGraphicsSceneHoverEvent *event); //if you are hovered over
    virtual void receiveHoverEvent(QGraphicsSceneHoverEvent *event);

    virtual void processColorChangeEvent( QColor newColor );

signals:
    void geometryChangedSignal( const QRectF &geom );
    void heightChangedSignal( float height );
    void widthChangedSignal( float width );
    void xPosChangedSignal( float xPos );
    void yPosChangedSignal( float yPos );
    void hoverConnectionSignal(QGraphicsSceneHoverEvent *event);
    virtual void colorChangedSignal(QColor);
    void updatedSignal();

    void recomputeLayoutSignal();

public slots:
    void geometryChangedSlot( const QRectF &geom );
    void heightChangedSlot( float height );
    void widthChangedSlot( float width );
    void xPosChangedSlot( float xPos );
    void yPosChangedSlot( float yPos );
    void hoverConnectionSlot(QGraphicsSceneHoverEvent *event);
    void colorChangedSlot(QColor);
    void updatedSlot();

    void hoverEnterEvent(QGraphicsSceneHoverEvent *event);
    void hoverLeaveEvent(QGraphicsSceneHoverEvent *event);


protected:
    QPointer<SageVis> sageVisPointer;/*< Pointer to the SageVis parent that controls this widget. */
    QPointer<VisBaseWidget> parentWidget;

    //if you want to emit a signal of a change in geometry
      //used to make sure the geometryChanged signal is not emited/recieved infinitely
      //generally true, unless this element has just recieved a signal to change geometry
    bool emitGeometryChangedSignal;
    bool emitWidthChangedSignal;
    bool emitHeightChangedSignal;
    bool emitXPosChangedSignal;
    bool emitYPosChangedSignal;
    bool emitHoverSignal;
    bool emitUpdatedSignal;
    bool emitColorChangedSignal;

    bool acceptHeightChanged;
    bool acceptWidthChanged;
    bool acceptXPosChanged;
    bool acceptYPosChanged;
    bool acceptHoverSignals;
    bool acceptUpdatedSignals;
    bool acceptColorChangedSignals;

    bool hovering;

    int lineConnectionType;
    QPointF lineConnectionPoint; //where a line connection element goes
    void resetLineConnectionPoint();


    
};


//TO DO:
//Problem with hovering:  say elt 1 is hover over and is hover connected to elt2.  If elt2 is connected to elt3,
//  if elt2 recieves a hover event it won't trigger a hover in elt3, even though it needs to.

#endif // VISBASEELEMENT_H
